ICTSC2019 一次予選 問題解説: 郷に入っては郷に従え

問題文

WEBサーバを運用する部署に所属することになったあなたは、前任者が構築したサーバを引き継ぐことになりました。現在の状態、発生した問題などについて、前任者の報告がありました。

LXCを使用してWEBサーバを構築しました。
コンテナではapacheが1234/tcpで起動しています。
LXCホストのiptablesでホスト80/tcpへの通信をコンテナ1234/tcpへ転送するDNATの設定をしました。
VNCサーバからLXCホストの80/tcpへアクセスすると無事にWEBサーバの起動を確認できました。
しかし、システムのアップデートをしようと思ったらコンテナからaptコマンドを使用できなくなりました。

どうやら、担当者は少々無理をしてコンテナのWEBサーバを外部に公開したようです。原因の究明と適切な設定を施してほしいです。設定は永続化し、再起動などが行えるようにしてください。

ゴール  

  • 外部(VNCサーバ)からLXCホスト80番でWEBページが確認できる(開始時点で閲覧可能だが、トラブルシューティング後も見られるようにすること)
  • コンテナ内で apt update ができる
  • 設定の永続化が行われている

問題サーバー  

  • IPアドレス: 192.168.0.1
  • ユーザー名: admin
  • パスワード: 3tRC7llZ
  • サービス名:dnat.service
  • コンテナ名:ubuntu-dnat

原因究明

iptablesのPREROUTINGチェインでDNATしているため、コンテナから外に出るときにもこのルールが適用されてしまう。

解説

現状の確認

初期状態だと、VNCサーバからLXCホスト80番でWEBページが確認できるのでまず確認してみる。

wget -O - 192.168.0.1

問題なくWEBページが公開できている。次に、問題サーバへ接続しスクリプトファイルを確認する。

#!/bin/bash
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.176.76.106:1234

どうやらsystemdを使ってiptablesを永続化させている。最後に発生している問題を確認する。

admin@lxc:~$ sudo lxc exec ubuntu-dnat /bin/bash
[sudo] password for admin: 
root@ubuntu-dnat:~# apt update
Err:1 http://archive.ubuntu.com/ubuntu bionic InRelease                                                                    
  Cannot initiate the connection to archive.ubuntu.com:80 (2001:67c:1360:8001::21). - connect (101: Network is unreachable) Cannot initiate the connection to archive.ubuntu.com:80 (2001:67c:1560:8001::11). - connect (101: Network is unreachable) Cannot initiate the connection to archive.ubuntu.com:80 (2001:67c:1560:8001::14). - connect (101: Network is unreachable) Cannot initiate the connection to archive.ubuntu.com:80 (2001:67c:1360:8001::17). - connect (101: Network is unreachable) Could not connect to archive.ubuntu.com:80 (91.189.88.24), connection timed out Could not connect to archive.ubuntu.com:80 (91.189.88.31), connection timed out Could not connect to archive.ubuntu.com:80 (91.189.88.149), connection timed out Could not connect to archive.ubuntu.com:80 (91.189.88.162), connection timed out
Err:2 http://archive.ubuntu.com/ubuntu bionic-updates InRelease        

名前解決はできるが、HTTP接続に問題があるようだ。

解決方法

下記の2つ、どちらかのルールに変更すれば、コンテナから外に出る80/tcpがルールが掛からなくなります。これでapt updateが正常に実行できます。

  • 公開しているネットワークのインターフェイス(th0)を指定する
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 10.176.76.106:1234
  • destinationを指定してLXCホスト宛にのみDNATを行う
iptables -t nat -A PREROUTING -p tcp -d 192.168.0.1/24 --dport 80 -j DNAT --to-destination 10.176.76.106:1234

ここまでで、9割の解答になります。

適切な方法

上記の方法で問題は解決できますが、適切であるとは言えません。問題文にある無理やりを解決する方法は以下の2つがあげれます。

  • lxc configを使用する
  • iptables-persistentを使用する
  • nginxを使用する(想定外)

lxc configを使用した方法

そもそもLXCにはコンテナを外部に公開するコマンドが用意されています。この問題のタイトル郷に入っては郷に従えはこの解法から決めました。

サービスの停止

sudo systemctl stop dnat.service
sudo systemctl disable dnat.service

lxc config でproxyを設定

sudo lxc config device add ubuntu-dnat http proxy listen=tcp:0.0.0.0:80 connect=tcp:10.176.76.106:1234 bind=host

iptables-persistentを使用した方法

本問題環境(ubuntu18)ではiptablesを永続化することはデフォルトではできません。そこでsystemdを使用して起動するたびにコマンドを実行していました。この点を無理やりと考えるとiptables-persistentを使用するのが適切です。

サービスを停止させます。

sudo systemctl stop dnat.service
sudo systemctl disable dnat.service

解決方法のルールを適応し、問題が解決している状態でiptables-persistentをインストールするとその状態で永続化されます。

sudo apt-get install iptables-persistent

nginxを使用した方法

あるチームが回答してくれた方法にnginxのリバースプロキシを使用する解法がありました。WEBを公開する手法として適切であると判断し、模範解答に追加しました。

admin@lxc:~$ cat /etc/nginx/conf.d/ictsc.conf 
server{
    proxy_set_header    Host    $host;
    proxy_set_header    X-Real-IP    $remote_addr;
    proxy_set_header    X-Forwarded-Host       $host;
    proxy_set_header    X-Forwarded-Server    $host;
    proxy_set_header    X-Forwarded-For    $proxy_add_x_forwarded_for;

    location / {
        proxy_pass    http://10.176.76.106:1234;

    }
}

採点基準

  • apt get が使用できる状態になっており、回答にコマンドと説明が記述されている :140点
  • 原因を究明し、回答に記述されている :40点
  • 適切な手法で解決し、回答に記述されている :20点